package com.topnav.mc.listener;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.js.lib.cache.Cache;
import com.topnav.mc.admin.entity.Device;
import com.topnav.mc.admin.service.IDeviceService;
import com.topnav.mc.listener.bean.YLDeviceInfo;
import com.topnav.mc.lock.SyncLock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @Author: kenny
 * @Date: 2023/10/27 13:35
 */
@Component
@Slf4j
public class RedisYlDeviceInfoMsgListener implements MessageListener {
    private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
    @Resource(name="sysCache")
    private Cache sysCache;
    @Autowired
    private IDeviceService deviceService;

    @Override
    public void onMessage(Message message, byte[] bytes) {
        taskQueue.offer(message);
        this.consusme();
    }

    @Async("taskExecutor")
    @SyncLock(key="RedisYlDeviceInfoMsgListener-consusGps-LOCK",dueSec = 5*60)
    public void consusme(){

        LambdaUpdateWrapper<Device> updateWrapper = new LambdaUpdateWrapper<>();
        //UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
        while (!taskQueue.isEmpty()) {
            Message msg = taskQueue.poll();
            YLDeviceInfo ylDeviceInfo = JSON.parseObject(msg.getBody(), YLDeviceInfo.class);
            log.info(">>>>> 收到设备状态信息：code:{}, 电量：{}，存储: {}, 内存: {},录像: {}, AES加密：{}",
                    ylDeviceInfo.getDeviceId(),
                    ylDeviceInfo.getBatteryInfo(),
                    ylDeviceInfo.getStorage(),
                    ylDeviceInfo.getRemainMemory(),
                    ylDeviceInfo.getRecordStatus(),
                    ylDeviceInfo.getStreamEncryption()
            );

            // 更新缓存
            Device device = deviceService.getDeviceFromCache(ylDeviceInfo.getDeviceId());
            if (device == null){
                continue;
            }

            //有变化才存到数据库
            boolean ischange = this.compareDevice(device,ylDeviceInfo);
            if  (ischange){
                device.setBatteryInfo(ylDeviceInfo.getBatteryInfo()+"%");
                if (!StringUtils.isEmpty(ylDeviceInfo.getStorage())){
                    device.setStorage(this.kToG(ylDeviceInfo.getStorage()));
                }
                if (!StringUtils.isEmpty(ylDeviceInfo.getUsedMemory())){
                    device.setUsedMemory(this.kToG(ylDeviceInfo.getUsedMemory()));
                }
                if (!StringUtils.isEmpty(ylDeviceInfo.getRemainMemory())){
                    device.setRemainMemory(this.kToG(ylDeviceInfo.getRemainMemory()));
                }

                device.setRecordStatus(ylDeviceInfo.getRecordStatus());
                device.setStreamEncryption(ylDeviceInfo.getStreamEncryption());
                //deviceService.saveToCache(device);
                //更新数据库
                updateWrapper.clear();
                updateWrapper.set(Device::getBatteryInfo,device.getBatteryInfo());
                updateWrapper.set(Device::getStorage,device.getStorage());
                updateWrapper.set(Device::getUsedMemory,device.getUsedMemory());
                updateWrapper.set(Device::getRemainMemory,device.getRemainMemory());
                updateWrapper.set(Device::getRecordStatus,device.getRecordStatus());
                updateWrapper.set(Device::getStreamEncryption,device.getStreamEncryption());
                updateWrapper.eq(Device::getId,device.getId());
                deviceService.update(updateWrapper);
            }
            try {
                Thread.sleep(5L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String kToG(String source){
        return String.valueOf(
                Math.round(
                        (Double.valueOf(source)/1000/1000) *100
                )/100.0

        ) + "G";
    }


    /**
     * 比较 Device 和 YLDeviceInfo 是否有变化，没变化则不能保存数据库
     * @param device
     * @param deviceInfo
     * @return 相等反回 true 不等 false
     */
    private boolean compareDevice(Device device,YLDeviceInfo deviceInfo){

        //batteryInfo
        if (!this.strCompare(device.getBatteryInfo(),deviceInfo.getBatteryInfo()+"%")){
            return true;
        }
        //存储空间 storage
        if (!this.strCompare(device.getStorage(),kToG(deviceInfo.getStorage()))){
            return true;
        }

        //使用内存 usedMemory;
        if (!this.strCompare(device.getUsedMemory(),kToG(deviceInfo.getUsedMemory()))){
            return true;
        }

        //空闲内存 remainMemory;
        if (!this.strCompare(device.getRemainMemory(),kToG(deviceInfo.getRemainMemory()))){
            return true;
        }


        //录像状态 0，未录像 1 正在录像  recordStatus;
        if (!this.strCompare(device.getRecordStatus(),deviceInfo.getRecordStatus())){
            return true;
        }


        // Aes加密密码 StreamEncryption;
        if (!this.strCompare(device.getStreamEncryption(),deviceInfo.getStreamEncryption())){
            return true;
        }
        return false;

    }

    /**
     * 字符比对是否相等
     * @param source
     * @param dest
     * @return 相等true, 不等 false
     */
    private boolean strCompare(String source, String dest){
        // 都为空或都不为空且相等
        if (!StringUtils.isEmpty(source) && !StringUtils.isEmpty(dest)){
            return source.equals(dest);
        }
        return StringUtils.isEmpty(source) && StringUtils.isEmpty(dest);
    }
}
